import base64
import json
import re

import cv2
import numpy as np
import requests

from codes.commons.configs import easiest_common_headers as common_headers


def get_img_base64_code(res_json):
    html_str = res_json['html']
    # 获取目标文字
    words_pattern = re.compile(r'<p>(.*?)</p>')
    words = words_pattern.findall(html_str)
    print(words)
    # 获取图片base64
    image_pattern = re.compile(r'src="(.*?)"')
    image_base64 = image_pattern.findall(html_str)[0].replace('data:image/jpeg;base64,', '')
    return base64.b64decode(image_base64.encode())


def write_pic_local():
    with open('../../resources/match8/verify1.json', mode='r', encoding='utf8') as f:
        v_json = json.load(f)
    with open('../../resources/match8/vf1.png', 'wb') as fp:
        fp.write(get_img_base64_code(v_json))
    print('写入完成！')


def get_verify(session, img_path):
    url = 'http://match.yuanrenxue.com/api/match/8_verify'
    r_json = session.get(url).json()
    with open(img_path, 'wb') as fp:
        fp.write(get_img_base64_code(r_json))
    print('验证图片已保存，待处理...')


def handle_image(img_path):
    im = cv2.imread(img_path)
    # img.shape可以获得图像的形状，返回值是一个包含行数，列数，通道数的元组 (100, 100, 3)
    h, w = im.shape[0:2]
    # 去掉黑椒点的图像
    # np.all()函数用于判断整个数组中的元素的值是否全部满足条件，如果满足条件返回True，否则返回False
    im[np.all(im == [0, 0, 0], axis=-1)] = (255, 255, 255)  # 将像素点为黑色的全部转换为白色的
    # reshape：展平成n行3列的二维数组
    # np.unique()该函数是去除数组中的重复数字，并进行排序之后输出
    colors, counts = np.unique(np.array(im).reshape(-1, 3), axis=0, return_counts=True)
    # 筛选出现次数在500~2200次的像素点
    # 通过后面的操作就可以移除背景中的噪点
    info_dict = {counts[i]: colors[i].tolist() for i, v in enumerate(counts) if 500 < int(v) < 2200}

    # 移除了背景的图片
    remove_background_rgbs = info_dict.values()
    mask = np.zeros((h, w, 3), np.uint8) + 255  # 生成一个全是白色的图片
    # 通过循环将不是噪点的像素,赋值给一个白色的图片,最后到达移除背景图片的效果
    for rgb in remove_background_rgbs:
        mask[np.all(im == rgb, axis=-1)] = im[np.all(im == rgb, axis=-1)]
    # cv2.imshow("Image with background removed", mask)  # 移除了背景的图片
    # cv2.waitKey(0)
    # cv2.imwrite('../../resources/match8/deal0.png', mask) # 保存处理的图片
    # 去掉线条，全部像素二值化
    line_list = []  # 创建空列表，用来存放出现在间隔当中的像素点
    # 循环遍历找出间隔中的像素点
    for y in range(h):
        for x in range(w):
            tmp = mask[x, y].tolist()
            if tmp != [0, 0, 0]:
                if 110 < y < 120 or 210 < y < 220:
                    line_list.append(tmp)
                if 100 < x < 110 or 200 < x < 210:
                    line_list.append(tmp)

    remove_line_rgbs = np.unique(np.array(line_list).reshape(-1, 3), axis=0)
    for rgb in remove_line_rgbs:
        mask[np.all(mask == rgb, axis=-1)] = [255, 255, 255]
    # np.any()函数用于判断整个数组中的元素至少有一个满足条件就返回True，否则返回False。
    mask[np.any(mask != [255, 255, 255], axis=-1)] = [0, 0, 0]
    # cv2.imshow('Image with lines removed', mask)
    # cv2.waitKey(0)

    # 腐蚀
    # 生成一个2行三列数值全为1的二维数字,作为腐蚀操作中的卷积核
    kernel = np.ones((2, 3), 'uint8')
    erode_img = cv2.erode(mask, kernel, cv2.BORDER_REFLECT, iterations=2)
    print('处理后的图片已保存，请查看...')
    cv2.imshow('Eroded Image', erode_img)
    cv2.waitKey(0)
    # cv2.destroyAllWindows()可以轻易删除任何我们建立的窗口，括号内输入想删除的窗口名
    cv2.destroyAllWindows()
    cv2.imwrite('../../resources/match8/temp_deal.png', mask)
    return 'temp_deal.png'


def get_page(page_num, index_list, session):
    url = 'http://match.yuanrenxue.com/api/match/8'
    click_dict = {
        '1': 126, '2': 136, '3': 146,
        '4': 426, '5': 466, '6': 476,
        '7': 726, '8': 737, '9': 747
    }
    answer = '|'.join([str(click_dict[i]) for i in index_list]) + '|'
    params = {
        'page': page_num,
        'answer': answer
    }
    response = session.get(url=url, params=params)
    try:
        value_list = [i['value'] for i in response.json()['data']]
        print(f'第{page_num}页的值为:{value_list}')
        return value_list
    except:
        print(f'第{page_num}页验证失败:{response.text}')
        return []


if __name__ == '__main__':
    temp_img_path = '../../resources/match8/temp_verify.png'
    real_session = requests.session()
    real_session.headers = common_headers
    answer_list = []
    for p in range(1, 6):
        while True:
            get_verify(real_session, temp_img_path)
            handle_image(temp_img_path)
            word_dict = input('请输入对应的坐标:')
            res = get_page(p, list(word_dict), real_session)
            if len(res) > 0:
                answer_list.extend(res)
                break
    print(f'出现次数最多的数字是:{max(set(answer_list), key=answer_list.count)}')
